#!/usr/bin/env python3
import os
import re
import shutil
import subprocess
import sys
from pathlib import Path
from tempfile import TemporaryDirectory
from datetime import datetime
from typing import Dict, List, Tuple, Set, Optional


class CheckHFileQuote:
    """头文件引用检查工具类"""

    def __init__(self, base_dir: Path, work_dir: Path, output_dir: Path, diff_file: Path, pr_number: int):
        """
        初始化检查器

        Args:
            base_dir: 基础代码目录
            work_dir: 工作目录
            output_dir: 输出目录
            diff_file: diff文件路径
        """
        self.base_dir = base_dir
        self.work_dir = work_dir
        self.output_dir = output_dir
        self.diff_file = diff_file  # 改为具体的diff文件
        self.pr_number = pr_number

        # 确保目录存在
        self.output_dir.mkdir(exist_ok=True, parents=True)
        self.work_dir.mkdir(exist_ok=True, parents=True)
        # 检查diff文件是否存在
        if not self.diff_file.exists():
            print(f"警告：diff文件不存在 {self.diff_file}")

    @staticmethod
    def parse_file(filename: Path) -> Dict[str, Tuple[str, Optional[str]]]:
        """解析文件，返回一个字典，key是:前的部分，value是整行内容和:后的数字"""
        result = {}
        try:
            with open(filename, 'r', encoding='utf-8') as f:
                for line in f:
                    line = line.strip()
                    if ':' in line:
                        key, value = line.split(':', 1)
                        result[key] = (line, value.strip())
                    else:
                        result[line] = (line, None)
        except FileNotFoundError:
            print(f"警告：文件不存在 {filename}")
        except Exception as e:
            print(f"解析文件 {filename} 时出错: {e}")
        return result

    @staticmethod
    def compare_files(file1: Path, file2: Path, output_name: str = None) -> Path:
        """
        比较两个文件并生成结果文件

        Args:
            file1: 第一个文件路径
            file2: 第二个文件路径
            output_name: 输出文件名

        Returns:
            生成的比较结果文件路径
        """
        if not output_name:
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            output_name = f"file_comparison_result_{timestamp}.txt"

        output_file = Path(output_name)

        dict1 = CheckHFileQuote.parse_file(file1)
        dict2 = CheckHFileQuote.parse_file(file2)

        with open(output_file, 'w', encoding='utf-8') as out:
            # 写入文件信息
            out.write(f"比较文件: {file1.name} 和 {file2.name}\n")
            out.write(
                f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
            out.write("=" * 50 + "\n\n")

            # 检查新增或修改的行
            out.write("=== 新增或修改的行 ===\n")
            changes_found = False
            for key in dict1:
                line1, value1 = dict1[key]
                if key in dict2:
                    line2, value2 = dict2[key]
                    if value1 != value2:
                        out.write(
                            f"修改: {line1} (原值: {value2 if value2 is not None else '无'})\n")
                        changes_found = True
                else:
                    out.write(f"新增: {line1}\n")
                    changes_found = True

            if not changes_found:
                out.write("无新增或修改的行\n")

            # 检查移除的行
            out.write("\n=== 移除的行 ===\n")
            removals_found = False
            for key in dict2:
                if key not in dict1:
                    line2, value2 = dict2[key]
                    out.write(f"移除: {line2}\n")
                    removals_found = True

            if not removals_found:
                out.write("无移除的行\n")

        print(f"比较结果已保存到: {output_file}")
        return output_file

    @staticmethod
    def apply_diff(diff_file: Path, target_dir: Path) -> bool:
        """
        将 diff 文件应用到目标目录

        Args:
            diff_file: diff文件路径
            target_dir: 目标目录路径

        Returns:
            True 如果应用成功，False 如果失败
        """
        print(f"\n=== 准备应用 {diff_file.name} 到 {target_dir} ===")

        # 验证目标目录是否存在
        if not target_dir.exists():
            print(f"错误：目标目录不存在 {target_dir}")
            return False

        # 检查是否已安装 patch 命令
        if not shutil.which('patch'):
            print("错误：系统未安装 'patch' 命令")
            return False

        # 检查diff文件是否存在
        if not diff_file.exists():
            print(f"错误：diff文件不存在 {diff_file}")
            return False

        try:
            # 保存当前目录
            original_dir = os.getcwd()
            os.chdir(target_dir)
            print(f"当前工作目录: {os.getcwd()}")

            # 执行 patch 命令
            cmd = ['patch', '-p1', '--no-backup-if-mismatch',
                   '--forward', '--input', str(diff_file)]
            print(f"执行命令: {' '.join(cmd)}")

            result = subprocess.run(
                cmd, capture_output=True, text=True, timeout=300)

            if result.returncode != 0:
                print(f"\n应用 diff 失败 (返回码 {result.returncode}):")
                print(result.stderr)
                return False

            print("\nDiff 应用成功！")
            if result.stdout.strip():
                print("变更摘要:")
                print(result.stdout)
            return True

        except subprocess.TimeoutExpired:
            print("应用 diff 超时")
            return False
        except Exception as e:
            print(f"\n发生错误: {str(e)}")
            return False
        finally:
            os.chdir(original_dir)

    def create_virtual_workspace(self) -> bool:
        """创建虚拟工作空间并执行构建流程（使用后自动删除）"""
        print("\n=== 创建虚拟工作空间 ===")

        # 检查diff文件是否存在
        if not self.diff_file.exists():
            print(f"错误：diff文件不存在 {self.diff_file}")
            return False
        
        try:
            # 使用 TemporaryDirectory，会在退出时自动删除
            with TemporaryDirectory(prefix="ace_workspace_", dir=self.work_dir) as temp_dir:
                temp_dir = Path(temp_dir)
                print(f"临时工作空间路径: {temp_dir}")
                print("⚠️ 注意：此工作空间将在流程完成后自动删除")

                # 1. 拷贝源代码
                workspace_ace = temp_dir / "ace_engine"
                print(f"\n拷贝源代码到: {workspace_ace}")
                
                if not self.base_dir.exists():
                    print(f"错误：基础代码目录不存在 {self.base_dir}")
                    return False
                
                # 确保目标目录不存在
                if workspace_ace.exists():
                    print(f"⚠️ 目标目录已存在，删除: {workspace_ace}")
                    shutil.rmtree(workspace_ace)
                
                shutil.copytree(self.base_dir, workspace_ace)
                print("✅ 源代码拷贝完成")

                # 2. 应用diff文件
                print("\n=== 应用diff文件 ===")
                diff_work_dir = workspace_ace / "foundation/arkui/ace_engine"
                
                # 确保目标目录存在
                if not diff_work_dir.exists():
                    print(f"创建目标目录: {diff_work_dir}")
                    diff_work_dir.mkdir(parents=True, exist_ok=True)
                
                if not self.apply_diff(self.diff_file, diff_work_dir):
                    print("应用diff失败，终止流程")
                    return False

                # 3. 执行构建/分析
                print("\n=== 执行头文件引用分析 ===")
                os.chdir(workspace_ace)
                
                # 检查脚本文件是否存在
                script_path = Path("get_hifle_counts.py")
                if not script_path.exists():
                    print(f"❌ 错误：分析脚本不存在 {script_path}")
                    return False

                # 执行头文件引用分析脚本
                build_cmd = [
                    "python", str(script_path),
                    "foundation/arkui/ace_engine",
                    "--exclude_dirs", "foundation/arkui/ace_engine/test",
                    "foundation/arkui/ace_engine/adapter/preview/",
                    "--include_dirs", "./",
                    "foundation/arkui/ace_engine",
                    "foundation/arkui/ace_engine/frameworks/",
                    "foundation/arkui/ace_engine/interfaces/inner_api/ace_kit/include/"
                ]

                print(f"执行命令: {' '.join(build_cmd)}")
                result = subprocess.run(
                    build_cmd, capture_output=True, text=True, timeout=600)

                if result.returncode != 0:
                    print(f"分析执行失败 (返回码 {result.returncode}):")
                    print("标准输出:", result.stdout)
                    print("错误输出:", result.stderr)
                    return False

                print("✅ 分析执行成功")
                if result.stdout.strip():
                    print("输出:")
                    print(result.stdout)

                # 4. 收集输出文件
                print("\n=== 收集分析结果 ===")
                

                file = Path("hfile_counts.txt")
                if not file.exists():
                    print(f"hfile_counts.txt 文件不存在")
                else:
                    dest = self.output_dir / file.name
                    if dest.exists():
                        print(f"⚠️ 目标文件已存在，删除: {dest}")
                        dest.unlink()
                os.system(f"cp {file.name} {self.output_dir / file.name}")

            # TemporaryDirectory 会在退出 with 块时自动删除
            print("\n✅ 虚拟工作空间流程完成")
            print("⚠️ 临时工作空间已自动删除")
            return True
        except Exception as e:
            print(f"\n❌ 创建虚拟工作空间时发生错误: {str(e)}")
            import traceback
            traceback.print_exc()
            return False

    def run_comparison(self, base_result: str, patch_result: str) -> Optional[Path]:
        """
        运行比较分析

        Args:
            base_result: 基础结果文件名
            patch_result: 补丁结果文件名

        Returns:
            比较结果文件路径，如果失败返回None
        """
        base_file = self.output_dir / base_result
        patch_file = self.output_dir / patch_result

        if not base_file.exists():
            print(f"错误：基础结果文件不存在 {base_file}")
            return None
        if not patch_file.exists():
            print(f"错误：补丁结果文件不存在 {patch_file}")
            return None

        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        output_name = f"comparison_result_{timestamp}.txt"

        return self.compare_files(base_file, patch_file, output_name)

    def cleanup(self):
        """清理临时文件"""
        print("\n=== 清理临时文件 ===")
        # 可以添加清理逻辑，如删除旧的输出文件等
        pass

